package com.xframe.xdal.core.model;


import com.xframe.xdal.core.constant.DalConstants;
import com.xframe.xdal.core.constant.SqlBuilderConstants;
import com.xframe.xdal.core.model.mapping.IColumnMapping;
import com.xframe.xdal.core.model.mapping.ITableInfo;
import com.xframe.xdal.core.model.sqlbuilder.BuilderContext;
import com.xframe.xdal.core.model.sqlbuilder.DbExpression;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 功能描述:set子句集合
 *
 * @author xufeng
 * @version 1.0
 * @date 2022-09-26
 */
@Data
@Log4j2
public class SetWrapCollection {
    /**
     * 查询条件对象集合
     */
    @Setter(AccessLevel.NONE)
    private Set<SetWrap> setWraps = new HashSet<>();

    /**
     * 添加一个子句
     *
     * @param setWrap 查询对象
     */
    public SetWrapCollection add(SetWrap setWrap) {
        setWraps.add(setWrap);
        return this;
    }

    /**
     * 添加一个子句
     *
     * @param fieldName 字段名称
     * @param val 字段值
     * @param mode 模式
     */
    public SetWrapCollection add(String fieldName,Object val,SetWrapMode mode) {
        setWraps.add(new SetWrap(fieldName,val,mode));
        return this;
    }

    /**
     * 添加一个子句
     *
     * @param fieldName 字段名称
     */
    public SetWrapCollection add(String fieldName) {
        setWraps.add(new SetWrap(fieldName));
        return this;
    }

    /**
     * 添加一个子句
     *
     * @param fieldName 字段名称
     * @param val 字段值
     */
    public SetWrapCollection add(String fieldName,Object val) {
        setWraps.add(new SetWrap(fieldName,val));
        return this;
    }

    /**
     * 添加一个子句 自增1的SET语句
     *
     * @param fieldName 字段名称
     */
    public SetWrapCollection addAutoincrement(String fieldName) {
        setWraps.add(new SetWrap(fieldName,1,SetWrapMode.AUTOINCREMENT));
        return this;
    }

    /**
     * 添加一个子句 自增val的SET语句
     *
     * @param fieldName 字段名称
     * @param val 自增的步长
     */
    public SetWrapCollection addAutoincrement(String fieldName,Object val) {
        setWraps.add(new SetWrap(fieldName,val,SetWrapMode.AUTOINCREMENT));
        return this;
    }

    /**
     * 添加一个子句 自减val的SET语句
     *
     * @param fieldName 字段名称
     * @param val 自减的步长
     */
    public SetWrapCollection addDecrement(String fieldName,Object val) {
        setWraps.add(new SetWrap(fieldName,val,SetWrapMode.DECREMENT));
        return this;
    }

    /**
     * 添加一个子句 自减val的SET语句
     *
     * @param fieldName 字段名称
     */
    public SetWrapCollection addDecrement(String fieldName) {
        setWraps.add(new SetWrap(fieldName,1,SetWrapMode.DECREMENT));
        return this;
    }

    /**
     * 添加一个子句 使用数据库表达式的SET语句
     *
     * @param fieldName 字段名称
     * @param val 数据库表达式
     */
    public SetWrapCollection addDBexp(String fieldName,String val) {
        setWraps.add(new SetWrap(fieldName,val,SetWrapMode.DBEXP));
        return this;
    }



    public void buildSet(BuilderContext context,ITableInfo tableInfo,
                         StringBuilder setBuilder, List<Object> pList){
        int index = 0;
        for (SetWrap setWrap:setWraps) {
            switch (setWrap.getMode()) {
                case KEYVALUE:
                    setBuilder.append(buildHelp(context, tableInfo, setWrap, pList));
                    break;
                case DBEXP:
                    setBuilder.append(buildHelpByDbExp(context, tableInfo, setWrap));
                    break;
                case AUTOINCREMENT:
                    setBuilder.append(buildHelpByAutoincrement(context, tableInfo, setWrap,DalConstants.SQL_ADD));
                    break;
                case DECREMENT:
                    setBuilder.append(buildHelpByAutoincrement(context, tableInfo, setWrap,DalConstants.SQL_SUB));
                    break;
                case KEYTOKEY:
                    setBuilder.append(buildHelpByKeytoKey(context, tableInfo, setWrap));
                    break;
            }
            if(index + 1 < setWraps.size()){
                setBuilder.append(SqlBuilderConstants.SPSET);
            }
            index++;
        }
    }
    private static String buildHelpByKeytoKey(BuilderContext context, ITableInfo refTableInfo, SetWrap setWrap){
        IColumnMapping columnMapping = refTableInfo.findOneByFieldName(setWrap.getFieldName());
        IColumnMapping sourceColumnMapping = refTableInfo.findOneByFieldName(setWrap.getVal().toString());
        if(columnMapping == null || sourceColumnMapping == null){
            return "";
        }
        return context.getColPlaceholder() + context.getNameConvert().toName(columnMapping.getName())
                + context.getColPlaceholder() + DalConstants.SQL_EQUAL + context.getColPlaceholder() +
                context.getNameConvert().toName(sourceColumnMapping.getName()) + context.getColPlaceholder();
    }

    private static String buildHelp(BuilderContext context, ITableInfo refTableInfo, SetWrap setWrap,List<Object> pList){
        IColumnMapping columnMapping = refTableInfo.findOneByFieldName(setWrap.getFieldName());
        if(columnMapping == null){
            return "";
        }
        if (columnMapping.getUseDbObjectFlag()) {
            String dbExp = DbExpression.getDbExpression().getExpression(columnMapping.getDbExpression(), context.getDataSourceTypeEnums());
            return context.getColPlaceholder() + context.getNameConvert().toName(columnMapping.getName()) + context.getColPlaceholder() +
                    DalConstants.SQL_EQUAL + dbExp;
        }else {
            pList.add(setWrap.getVal());
            return context.getColPlaceholder() + context.getNameConvert().toName(columnMapping.getName()) + context.getColPlaceholder() +
                    DalConstants.SQL_EQUAL + DalConstants.SQL_PLACE_HOlDER;
        }
    }

    private static String buildHelpByDbExp(BuilderContext context, ITableInfo refTableInfo, SetWrap setWrap){
        IColumnMapping columnMapping = refTableInfo.findOneByFieldName(setWrap.getFieldName());
        if(columnMapping == null){
            return "";
        }
        String colName = context.getColPlaceholder() + context.getNameConvert().toName(columnMapping.getName()) + context.getColPlaceholder();

        return colName + DalConstants.SQL_EQUAL + DbExpression.getDbExpression().getExpression(setWrap.getVal().toString(),context.getDataSourceTypeEnums());

    }


    private static String buildHelpByAutoincrement(BuilderContext context, ITableInfo refTableInfo, SetWrap setWrap,String opString){
        IColumnMapping columnMapping = refTableInfo.findOneByFieldName(setWrap.getFieldName());
        if(columnMapping == null){
            return "";
        }
        String colName = context.getColPlaceholder() + context.getNameConvert().toName(columnMapping.getName()) + context.getColPlaceholder();

        return colName + DalConstants.SQL_EQUAL + colName + opString + setWrap.getVal().toString();

    }

}
